home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
68kdis.zip
/
ISET.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-03
|
25KB
|
1,223 lines
/*
* SCCS: @(#)iset.c 1.2 11/2/84 14:18:23
* Decode instructions.
*
***********************************************************************
* This software is copyright of
*
* John M Collins
* 47 Cedarwood Drive
* St Albans
* Herts, AL4 0DN
* England +44 727 57267
*
* and is released into the public domain on the following conditions:
*
* 1. No free maintenance will be guaranteed.
* 2. Nothing may be based on this software without
* acknowledgement, including incorporation of this
* notice.
*
* Notwithstanding the above, the author welcomes correspondence and bug
* fixes.
***********************************************************************
*/
#include <stdio.h>
#include <a.out.h>
#include <ldfcn.h>
#include "unc.h"
ef_fids mainfile;
long endt;
void gette(), putte();
void mkdref();
long gettw();
symbol textlab();
int l1(), l2(), el1(), lea(), lmove(), lcbch(), jj();
int limed(), lsbit(), lmvml(), lone(), loone(), lonew(), lonel();
int pmove(), pcbch(), pdbcc(), pscc(), pcs(), pmovc(), pstop(), pexg();
int pimed(), pmovp(), psbit(), pdbit(), pcs2(), pone(), ppea();
int plea(), pdreg(), pmvml(), ptrap(), plink(), pareg(), podreg();
int pqu(), pmqu(), ptreg(), pcmpm(), pomode(), pmshf(), pshf();
struct opstr {
unsigned short mask;
unsigned short match;
int (*opsize)();
int (*opprin)();
char *prarg;
} optab[] = {
0xf000, 0x2000, lmove, pmove, ".l",
0xf000, 0x3000, lmove, pmove, ".w",
0xf000, 0x1000, lmove, pmove, ".b",
0xf000, 0x6000, lcbch, pcbch, 0,
0xffbf, 0x003c, l2, pcs, "or",
0xff00, 0x0000, limed, pimed, "or",
0xffbf, 0x023c, l2, pcs, "and",
0xff00, 0x0200, limed, pimed, "and",
0xff00, 0x0400, limed, pimed, "sub",
0xff00, 0x0600, limed, pimed, "add",
0xffbf, 0x0a3c, l2, pcs, "eor",
0xff00, 0x0a00, limed, pimed, "eor",
0xff00, 0x0c00, limed, pimed, "cmp",
0xf138, 0x0108, l2, pmovp, 0,
0xff00, 0x0800, lsbit, psbit, 0,
0xf100, 0x0100, lonew, pdbit, 0,
0xffc0, 0x40c0, lonew, pcs2, "sr",
0xff00, 0x4000, lone, pone, "negx",
0xff00, 0x4200, lone, pone, "clr",
0xffc0, 0x44c0, lonew, pcs2, "cc",
0xff00, 0x4400, lone, pone, "neg",
0xffc0, 0x46c0, lonew, pcs2, "sr",
0xff00, 0x4600, lone, pone, "not",
0xffc0, 0x4800, lonew, ppea, "nbcd",
0xfff8, 0x4840, l1, pdreg, "swap.w",
0xffc0, 0x4840, lonel, ppea, "pea",
0xfff8, 0x4880, l1, pdreg, "ext.w",
0xfff8, 0x48c0, l1, pdreg, "ext.l",
0xfb80, 0x4880, lmvml, pmvml, 0,
0xffc0, 0x4ac0, lonew, ppea, "tas",
0xff00, 0x4a00, lone, pone, "tst",
0xfff0, 0x4e40, l1, ptrap, 0,
0xfff8, 0x4e50, l2, plink, 0,
0xfff8, 0x4e58, l1, pareg, "unlk\t%s",
0xfff8, 0x4e60, l1, pareg, "mov.l\t%s,%%usp",
0xfff8, 0x4e68, l1, pareg, "mov.l\t%%usp,%s",
0xffff, 0x4e70, l1, pareg, "reset",
0xffff, 0x4e71, l1, pareg, "nop",
0xffff, 0x4e72, l2, pstop, 0,
0xffff, 0x4e73, el1, pareg, "rte",
0xffff, 0x4e75, el1, pareg, "rts",
0xffff, 0x4e76, l1, pareg, "trapv",
0xffff, 0x4e77, el1, pareg, "rtr",
0xfffe, 0x4e7a, l2, pmovc, 0,
0xffc0, 0x4e80, jj, ppea, "jsr",
0xffc0, 0x4ec0, jj, ppea, "jmp",
0xf1c0, 0x4180, lonew, podreg,"chk",
0xf1c0, 0x41c0, lonel, plea, 0,
0xf0f8, 0x50c8, lcbch, pdbcc, 0,
0xf0c0, 0x50c0, lonew, pscc, 0,
0xf100, 0x5000, lone, pqu, "add",
0xf100, 0x5100, lone, pqu, "sub",
0xf100, 0x7000, l1, pmqu, 0,
0xf1c0, 0x80c0, lonew, podreg,"divu",
0xf1c0, 0x81c0, lonew, podreg,"divs",
0xf1f0, 0x8100, l1, ptreg, "sbcd",
0xf000, 0x8000, loone, pomode,"or",
0xf1f0, 0x9100, l1, ptreg, "subx.b",
0xf1f0, 0x9140, l1, ptreg, "subx.w",
0xf1f0, 0x9180, l1, ptreg, "subx.l",
0xf000, 0x9000, loone, pomode,"sub",
0xf1f8, 0xb108, l1, pcmpm, "cmp.b", /* CMPM */
0xf1f8, 0xb148, l1, pcmpm, "cmp.w", /* CMPM */
0xf1f8, 0xb188, l1, pcmpm, "cmp.l", /* CMPM */
0xf100, 0xb000, loone, pomode,"cmp",
0xf1c0, 0xb1c0, loone, pomode,"cmp",
0xf100, 0xb100, loone, pomode,"eor",
0xf1c0, 0xc0c0, lonew, podreg,"mulu",
0xf1c0, 0xc1c0, lonew, podreg,"muls",
0xf1f0, 0xc100, l1, ptreg, "abcd",
0xf130, 0xc100, l1, pexg, 0,
0xf000, 0xc000, loone, pomode,"and",
0xf1f0, 0xd100, l1, ptreg, "addx.b",
0xf1f0, 0xd140, l1, ptreg, "addx.w",
0xf1f0, 0xd180, l1, ptreg, "addx.l",
0xf000, 0xd000, loone, pomode,"add",
0xf8c0, 0xe0c0, lonew, pmshf, 0,
0xf000, 0xe000, l1, pshf, 0,
0
};
char *areg[] = { "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp"};
char *cclist[] = { "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs",
"pl", "mi", "ge", "lt", "gt", "le"};
char *shtype[] = { "as", "ls", "rox", "ro" };
char *bittyp[] = { "tst", "chg", "clr", "set" };
char *creg[] = { "%sfc", "%dfc", "%usp", "%vbr" };
int swbegflg = 0;
/*
* Length functions.
*/
int l1()
{
return 1;
}
int l2()
{
return 2;
}
int el1(te)
t_entry *te;
{
te->t_bchtyp = T_UNBR;
return 1;
}
int lea(instr, size, pos)
unsigned instr, size;
long pos;
{
switch ((instr >> 3) & 0x7) {
case 0:
case 1:
case 2:
case 3:
case 4:
return 1;
case 5:
case 6:
return 2;
default:
switch (instr & 0x7) {
case 0:
case 2:
case 3:
return 2;
case 1:
mkdref(pos, size);
return 3;
case 4:
if (size > 2)
return 3;
return 2;
default:
return 0;
}
}
}
/*
* Lengths of move instructions.
*/
int lmove(te, pos)
t_entry *te;
long pos;
{
register unsigned tc = te->t_contents;
unsigned sz = 1;
int lng, lng2;
lng = tc & 0xf000;
if (lng == 0x3000)
sz = 2;
else if (lng == 0x2000)
sz = 4;
if ((lng = lea(tc, sz, pos+2)) <= 0)
return 0;
lng2 = lea(((tc>>3) & 0x38) | ((tc>>9) & 0x7), sz, pos+lng+lng);
if (lng2 <= 0)
return 0;
return lng + lng2 - 1;
}
/*
* Lengths for conditional branches and dbcc instructions.
*/
int lcbch(te, pos)
t_entry *te;
long pos;
{
unsigned tc = te->t_contents;
long dest = pos + 2;
int res = 2;
if ((tc & 0xf000) == 0x5000 || (tc & 0xff) == 0)
dest += (short)gettw(&mainfile, pos+2, R_WORD);
else {
dest += (char) tc;
res = 1;
}
if ( dest < 0x290000 && (dest < mainfile.ef_tbase
|| dest >= mainfile.ef_tbase+mainfile.ef_tsize
|| (dest & 1) != 0 ))
return 0; /* Illegal branch destination */
if ((tc & 0xff00) == 0x6000)
te->t_bchtyp = T_UNBR;
else if ((tc & 0xff00) == 0x6100)
te->t_bchtyp = T_JSR;
else
te->t_bchtyp = T_CONDBR;
if ( dest < 0x290000 && ((te->t_relsymb = textlab(dest, pos)) == NULL )) {
te->t_bchtyp = T_NOBR;/* Branch to a continuation */
return 0;
}
return res;
}
int jj(te, pos)
t_entry *te;
long pos;
{
unsigned tc = te->t_contents;
t_entry nextl;
long dest;
te->t_bchtyp = (tc & 0x40)? T_UNBR: T_JSR;
if ((tc & 0x3f) == 0x39) {
gette(&mainfile, pos+2, &nextl);
if (nextl.t_relsymb == NULL) {
dest = gettw(&mainfile, pos + 2, R_LONG );
if ( dest < 0x290000 && (dest < mainfile.ef_tbase
|| dest >= mainfile.ef_tbase+mainfile.ef_tsize
|| (dest & 1) != 0 ))
return 0; /* Illegal branch destination */
if ( dest < 0x290000 && ( nextl.t_relsymb = textlab(dest, pos) ) == NULL )
return 0; /* Branch to a continuation */
putte(&mainfile, pos+2, &nextl);
}
te->t_relsymb = nextl.t_relsymb; /* Easy ref */
}
else if ((tc & 0x3f) == 0x3a) {
gette(&mainfile, pos+2, &nextl);
if (nextl.t_relsymb == NULL) {
dest = pos+2+ (int)((short)
gettw(&mainfile, pos + 2, R_WORD ));
if ( dest < 0x290000 && (dest < mainfile.ef_tbase
|| dest >= mainfile.ef_tbase+mainfile.ef_tsize
|| (dest & 1) != 0 ))
return lea(tc, 4, pos+2);
if (dest < 0x290000 &&
(nextl.t_relsymb = textlab(dest, pos)) == NULL)
return 0; /* Branch to a continuation */
putte(&mainfile, pos+2, &nextl);
}
te->t_relsymb = nextl.t_relsymb; /* Easy ref */
}
return lea(tc, 4, pos+2);
}
int limed(te, pos)
t_entry *te;
long pos;
{
unsigned tc = te->t_contents;
int lng;
/*
* Specifically exclude byte address register operands,
* and ones which have lengths of 3.
*/
if ((tc & 0xf8) == 0x08)
return 0;
if ((tc & 0xc0) >= 0x80) {
if (tc & 0x40)
return 0;
lng = lea(tc, 4, pos+6);
if (lng >